package com.idp.saml;

import com.idp.metadata.MetadataBean;
import org.opensaml.common.SAMLObject;
import org.opensaml.common.binding.BasicSAMLMessageContext;
import org.opensaml.saml2.binding.decoding.HTTPRedirectDeflateDecoder;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
import org.opensaml.xml.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.security.PublicKey;


public class AuthnRequestResolution {
    private static final Logger logger = LoggerFactory.getLogger(AuthnRequestResolution.class);
    private AuthnRequest authnRequest;
    private HttpServletRequest request;

    public AuthnRequestResolution(HttpServletRequest request) {
        this.request = request;
    }

    public AuthnRequest resolve(HttpServletRequest request) throws Exception {
        BasicSAMLMessageContext<AuthnRequest, ?, ?> messageContext = new BasicSAMLMessageContext<AuthnRequest, SAMLObject, SAMLObject>();
        messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(request));
        HTTPRedirectDeflateDecoder decoder = new HTTPRedirectDeflateDecoder();

        try {
            decoder.decode(messageContext);
        } catch (Exception e) {
            logger.error("", e);
//            throw new Exception("decode SAMLRequest error");
        }
        this.authnRequest = messageContext.getInboundSAMLMessage();
        this.request = request;
        return this.authnRequest;
    }

    public boolean verifySignature(MetadataBean spMetadata) {
        boolean verify = false;
        PublicKey publicKey = spMetadata.getSigningCredList().get(0).getPublicKey();

        String samlRequest = request.getParameter(AuthnRequestParameterConst.SAML_REQUEST);
        String relayState = request.getParameter(AuthnRequestParameterConst.RELAY_STATE);
        String sigAlg = request.getParameter(AuthnRequestParameterConst.SIG_ALG);
        String signature = request.getParameter(AuthnRequestParameterConst.SIGNATURE);

        byte[] decodeSignature = Base64.decode(signature);
        byte[] signedData = SignatureMethod.concat(samlRequest, relayState, sigAlg);
        try {
            String signatureAlgorithm = SignatureMethod.extractSignatureAlgorithm(sigAlg);
            verify = SignatureMethod.verifyStringSignature(decodeSignature, signedData, signatureAlgorithm, publicKey);
        } catch (Exception e) {
            logger.error("", e);
            return false;
        }
        return verify;
    }
}
